import { AudioClip, AudioSource, Component, director, game, Game, Node, resources } from "cc";

export class AudioSys extends Component {
  private static _instance: AudioSys;
  public static get instance(): AudioSys {
    if (!this._instance) {
      let rootNode: Node = new Node("AudioSys");
      director.addPersistRootNode(rootNode);
      this._instance = rootNode.addComponent(AudioSys);
      this._instance.init();
    }

    return this._instance;
  }

  private _musicAs: AudioSource;
  private _soundAs: AudioSource;

  private static readonly MinMusicVolume: number = 0;
  private static readonly MaxMusicVolume: number = 0.5;
  private static readonly MinSoundVolume: number = 0;
  private static readonly MaxSoundVolume: number = 1;
  private static readonly MusicFadeDuration: number = 1;
  private static readonly MusicFadeInterval: number = 0.05;

  public get isSoundMute(): boolean {
    return this._soundAs.volume == AudioSys.MinSoundVolume;
  }
  public get isMusicMute(): boolean {
    return this._musicAs.volume == AudioSys.MinMusicVolume;
  }

  onDestroy() {
    this.myDestroy();
  }

  private init(): void {
    this._musicAs = this.createAs(AudioSys.MaxMusicVolume, true);
    this._soundAs = this.createAs(AudioSys.MaxSoundVolume, false);
  }

  private createAs(volume: number, isLoop: boolean): AudioSource {
    let curAs: AudioSource = this.node.addComponent(AudioSource);
    curAs.clip = null;
    curAs.loop = isLoop;
    curAs.playOnAwake = false;
    curAs.volume = volume;
    return curAs;
  }

  public myDestroy(): void {
    let node: Node = AudioSys.instance.node;
    node.destroy();
    AudioSys._instance = null;
  }

  // 音乐：静音
  public muteMusic(): void {
    this._musicAs.volume = AudioSys.MinMusicVolume;
  }
  // 音效：静音
  public muteSound(): void {
    this._soundAs.volume = AudioSys.MinSoundVolume;
  }
  // 音乐：取消静音ß
  public cancelMuteMusic(): void {
    this._musicAs.volume = AudioSys.MaxMusicVolume;
  }
  // 音效：取消静音
  public cancelMuteSound(): void {
    this._soundAs.volume = AudioSys.MaxSoundVolume;
  }
  // 播放指定音乐（传入clip， 默认循环，淡入淡出）
  public playMusic(clip: AudioClip): void {
    this.unschedule(this.musicFadeIn);
    this.unschedule(this.musicFadeOut);

    if (this.isMusicMute) {
      this._musicAs.stop();
      this._musicAs.clip = clip;
      this._musicAs.play();
      return;
    }

    if (this._musicAs.clip) {
      // 淡出淡入
      this._musicAs.volume = AudioSys.MaxMusicVolume;
      this.schedule(
        this.musicFadeOut,
        AudioSys.MusicFadeInterval,
        AudioSys.MusicFadeDuration / AudioSys.MusicFadeInterval,
        0
      );
      setTimeout(() => {
        this._musicAs.stop();
        this._musicAs.volume = AudioSys.MinMusicVolume;
        this._musicAs.clip = clip;
        this._musicAs.play();
        this.schedule(
          this.musicFadeIn,
          AudioSys.MusicFadeInterval,
          AudioSys.MusicFadeDuration / AudioSys.MusicFadeInterval,
          0
        );
      }, AudioSys.MusicFadeDuration * 1000);
    } else {
      // 直接淡入
      this._musicAs.volume = AudioSys.MinMusicVolume;
      this._musicAs.clip = clip;
      this._musicAs.play();
      this.schedule(
        this.musicFadeIn,
        AudioSys.MusicFadeInterval,
        AudioSys.MusicFadeDuration / AudioSys.MusicFadeInterval,
        0
      );
    }
  }

  private musicFadeOut(): void {
    let volume =
      this._musicAs.volume -
      (AudioSys.MaxMusicVolume - AudioSys.MinMusicVolume) / (AudioSys.MusicFadeDuration / AudioSys.MusicFadeInterval);
    volume = volume < 0 ? 0 : volume;
    this._musicAs.volume = volume;
    0;
  }
  private musicFadeIn(): void {
    let volume =
      this._musicAs.volume +
      (AudioSys.MaxMusicVolume - AudioSys.MinMusicVolume) / (AudioSys.MusicFadeDuration / AudioSys.MusicFadeInterval);
    volume = volume > AudioSys.MaxMusicVolume ? AudioSys.MaxMusicVolume : volume;
    this._musicAs.volume = volume;
  }

  // 播放音效（传入clip）
  public playSound(clip: AudioClip): void {
    this._soundAs.playOneShot(clip, 1);
  }
}
